package com.ruoyi.ring.service.impl;
import cn.xfyun.api.LfasrClient;
import cn.xfyun.api.TtsClient;
import cn.xfyun.config.LfasrFailTypeEnum;
import cn.xfyun.config.LfasrOrderStatusEnum;
import cn.xfyun.model.response.TtsResponse;
import cn.xfyun.model.response.lfasr.LfasrOrderResult;
import cn.xfyun.model.response.lfasr.LfasrResponse;
import cn.xfyun.service.tts.AbstractTtsWebSocketListener;
import com.alibaba.fastjson2.JSONObject;
import com.google.gson.Gson;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.bean.Builder;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.ring.domain.RingVoiceRecord;
import com.ruoyi.ring.domain.VoiceSegment;
import com.ruoyi.ring.domain.VoiceTranModel;
import com.ruoyi.ring.service.IRingVoiceRecordService;
import com.ruoyi.ring.service.IVoiceTranslatService;
import okhttp3.Response;
import okhttp3.WebSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class VoiceTranslatXfyunServiceImpl implements IVoiceTranslatService {

    private static final Logger logger = LoggerFactory.getLogger(VoiceTranslatXfyunServiceImpl.class);

    private IRingVoiceRecordService voiceRecordService = SpringUtils.getBean(IRingVoiceRecordService.class);

    private static final Gson GSON = new Gson();

    /**
     * 服务鉴权参数
     */
    /***我自己的账号****/
//    private static final String APP_ID = "b998526e";
//    private static final String SECRET_KEY = "ac8aef471189e3e12324c45ff62b4378";

    /***客户账号 ****/
    private static final String appId = "1ebb0ce6";
    private static final String apiKey = "ee4c3609fbfe12b7150479e8e272afbf";
    private static final String apiSecret = "NzBlYTQwOGE5MzIyNDliOTVjYThmZjQ0";
    private static final String lfasrSecretKey = "d6a0039e811997509e464538736dcb76";


    /**
     * 任务类型
     * - transfer：转写
     * - translate：翻译（配合参数transLanguage和transMode使用）
     * - predict：质检（配合控制台质检词库使用）
     * - transfer,predict：转写 + 质检
     */
    private static final String TASK_TYPE = "transfer";


    @Override
    public VoiceTranModel voiceTranslat(String voicePath) {
        try {
            return getTransText(voicePath);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public AjaxResult voiceTranslat(RingVoiceRecord voiceRecord) {

        try {

//            HttpRequest request = new HttpRequest();
//            String result = request.sendFile("http://218.17.184.249:55000/transcribe", new FileSystemResource(voiceRecord.getVoicePath().replace(Constants.RESOURCE_PREFIX, RuoYiConfig.getProfile())));

//            String result = getTransText("D://1750303139_20250619111905A095.amr");

            VoiceTranModel transText = getTransText(voiceRecord.getVoicePath().replace(Constants.RESOURCE_PREFIX, RuoYiConfig.getProfile()));

            logger.info("Voice记录id【"+voiceRecord.getId()+"】，转写结果："+JSONObject.toJSONString(transText));

            if (transText != null && Constants.SUCCESS.equals(String.valueOf(transText.getCode()))) {

                voiceRecordService.tranFinishHandle(voiceRecord, transText);
            }
            return AjaxResult.success();
        }catch (Exception e){
            e.printStackTrace();
            return AjaxResult.error();
        }
    }

    @Override
    public VoiceTranModel textTranVoice(String content, String voicePath) {
        try {
            //  文字转音频
            TtsClient ttsClient = new TtsClient.Builder()
                    .signature(appId, apiKey, apiSecret)
                    .build();

            File file = new File(RuoYiConfig.getProfile() + voicePath);
            FileUploadUtils.getAbsoluteFile(file.getParent(), file.getName());

            CountDownLatch latch = new CountDownLatch(1);
            ttsClient.send(content, new AbstractTtsWebSocketListener(file) {
                @Override
                public void onSuccess(byte[] bytes) {
                    logger.info("语音合成成功，音频文件路径：{}，合成内容：{}", file.getAbsolutePath(), content);
                    latch.countDown();
                }

                @Override
                public void onFail(WebSocket webSocket, Throwable throwable, Response response) {
                    logger.error("语音合成失败，音频文件路径：{}，错误信息：{}", file.getAbsolutePath(), throwable.getMessage());
                    latch.countDown();
                }

                @Override
                public void onBusinessFail(WebSocket webSocket, TtsResponse ttsResponse) {
                    logger.error("语音合成业务失败，音频文件路径：{}，错误信息：{}", file.getAbsolutePath(), ttsResponse.toString());
                    latch.countDown();
                }
            });

            latch.await();
            VoiceTranModel voiceTranModel = new VoiceTranModel();

            voiceTranModel.setText(content);
            voiceTranModel.setVoicePath(Constants.RESOURCE_PREFIX + voicePath);
            voiceTranModel.setCode(Integer.valueOf(Constants.SUCCESS));
            return voiceTranModel;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    private VoiceTranModel printResult(LfasrResponse resultResponse) {
        switch (TASK_TYPE) {
            case "transfer":
                return parseOrderResult(resultResponse.getContent().getOrderResult());
//            case "translate":
//                parseTransResult(resultResponse.getContent().getTransResult());
//                break;
//            case "predict":
//                parsePredictResult(resultResponse.getContent().getPredictResult());
//                break;
//            case "transfer,predict":
//                parseOrderResult(resultResponse.getContent().getOrderResult());
//                parsePredictResult(resultResponse.getContent().getPredictResult());
//                break;
            default:
                logger.error("未知的任务类型：{}", TASK_TYPE);
                break;
        }
        return null;
    }

    /**
     * 解析转写结果
     */
    private VoiceTranModel parseOrderResult(String orderResultStr) {
        try {
            LfasrOrderResult orderResult = GSON.fromJson(orderResultStr, LfasrOrderResult.class);
//            logger.info("转写结果：\n{}", getLatticeText(orderResult.getLattice()));
            return getLatticeText(orderResult.getLattice());
        } catch (Exception e) {
            logger.error("转写结果解析失败", e);
        }
        return null;
    }

    /**
     * 从转写结果的lattice数组中提取文本
     */
    private VoiceTranModel getLatticeText(List<LfasrOrderResult.Lattice> latticeList) {
        VoiceTranModel voideModel = new VoiceTranModel();
        StringBuffer sb = new StringBuffer();
        List<VoiceSegment> segments = new ArrayList<>();
        for (LfasrOrderResult.Lattice lattice : latticeList) {
            LfasrOrderResult.Json1Best json1Best = lattice.getJson1Best();
            if (json1Best == null || json1Best.getSt() == null || json1Best.getSt().getRt() == null) {
                continue;
            }
            String rl = json1Best.getSt().getRl();
            StringBuilder rlText = getRlText(json1Best);
            sb.append(rlText);
//            resultText.append("角色-").append(rl).append("：").append(rlText).append("\n");
            segments.add(Builder.of(VoiceSegment::new)
                    .with(VoiceSegment::setRole, rl)
                    .with(VoiceSegment::setText, rlText.toString())
                    .with(VoiceSegment::setStart, String.valueOf(Integer.parseInt(json1Best.getSt().getBg()) / 1000.0))
                    .with(VoiceSegment::setEnd, String.valueOf(Integer.parseInt(json1Best.getSt().getEd()) / 1000.0))
                    .build());

            voideModel.setTotalDuration(String.valueOf(Integer.parseInt(json1Best.getSt().getEd()) / 1000.0));
        }

        voideModel.setSegments(segments);
        voideModel.setCode(Integer.valueOf(Constants.SUCCESS));
        voideModel.setText(sb.toString());
        return voideModel;
    }

    /**
     * 从Json1Best中提取识别结果文本并拼接
     */
    private static StringBuilder getRlText(LfasrOrderResult.Json1Best json1Best) {
        StringBuilder rlText = new StringBuilder();
        for (LfasrOrderResult.RecognitionResult rt : json1Best.getSt().getRt()) {
            if (rt.getWs() == null) {
                continue;
            }
            for (LfasrOrderResult.WordResult ws : rt.getWs()) {
                if (ws.getCw() != null && !ws.getCw().isEmpty()) {
                    // 获取每个词的识别结果
                    String word = ws.getCw().get(0).getW();
                    if (word != null && !word.isEmpty()) {
                        rlText.append(word);
                    }
                }
            }
        }
        return rlText;
    }

    @Override
    public AjaxResult realVoiceTranslat() {

        return null;
    }

    public static void main(String[] args) throws Exception{
        VoiceTranModel transText = new VoiceTranslatXfyunServiceImpl().getTransText("D://1750303139_20250619111905A095.amr");
        System.out.println(JSONObject.toJSONString(transText));
    }

    public VoiceTranModel getTransText(String audioFilePath) throws Exception{
        // 1、创建客户端实例
        LfasrClient lfasrClient = new LfasrClient.Builder(appId, lfasrSecretKey)
                // .roleType((short) 1)
                // .transLanguage("en")
                // .audioMode("urlLink")
                .build();

        // 2、上传音频文件（本地/Url）
        logger.info("音频上传中...");
//        audioFilePath = "D://1750303139_20250619111905A095.amr";
        LfasrResponse uploadResponse = lfasrClient.uploadFile(audioFilePath);
        if (uploadResponse == null) {
            logger.error("上传失败，响应为空");
            return null;
        }
        if (!org.apache.commons.codec.binary.StringUtils.equals(uploadResponse.getCode(), "000000")) {
            logger.error("上传失败，错误码：{}，错误信息：{}", uploadResponse.getCode(), uploadResponse.getDescInfo());
            return null;
        }
        String orderId = uploadResponse.getContent().getOrderId();
        logger.info("转写任务orderId：{}", orderId);

        // 3、查询转写结果
        int status = LfasrOrderStatusEnum.CREATED.getKey();
        // 循环直到订单完成或失败
        while (status != LfasrOrderStatusEnum.COMPLETED.getKey() && status != LfasrOrderStatusEnum.FAILED.getKey()) {
            LfasrResponse resultResponse = lfasrClient.getResult(orderId, TASK_TYPE);
            if (!org.apache.commons.codec.binary.StringUtils.equals(resultResponse.getCode(), "000000")) {
                logger.error("转写任务失败，错误码：{}，错误信息：{}", resultResponse.getCode(), resultResponse.getDescInfo());
                return null;
            }

            // 获取订单状态信息
            if (resultResponse.getContent() != null && resultResponse.getContent().getOrderInfo() != null) {
                status = resultResponse.getContent().getOrderInfo().getStatus();
                int failType = resultResponse.getContent().getOrderInfo().getFailType();

                // 根据状态输出日志
                LfasrOrderStatusEnum statusEnum = LfasrOrderStatusEnum.getEnum(status);
                if (statusEnum != null) {
                    logger.info("订单状态：{}", statusEnum.getValue());

                    // 如果订单失败，输出失败原因
                    if (statusEnum == LfasrOrderStatusEnum.FAILED) {
                        LfasrFailTypeEnum failTypeEnum = LfasrFailTypeEnum.getEnum(failType);
                        logger.error("订单处理失败，失败原因：{}", failTypeEnum.getValue());
                        return null;
                    }
                    // 如果订单已完成，输出结果
                    if (statusEnum == LfasrOrderStatusEnum.COMPLETED) {
                        return printResult(resultResponse);
                    }
                } else {
                    logger.error("未知的订单状态：{}", status);
                }
            } else {
                logger.error("返回结果中缺少订单信息");
            }

            TimeUnit.MILLISECONDS.sleep(2000);
        }
        return null;
    }

}
